use std::default::Default;
use std::num::ToPrimitive;
use std::os;
-use std::path::Path;
+use std::path::{Path, PathBuf};
use std::sync::Arc;
use core::registry::PackageRegistry;
use core::resolver::Method;
use ops::{self, BuildOutput, ExecEngine};
use sources::{PathSource};
-use util::config::Config;
+use util::config::{ConfigValue, Config};
use util::{CargoResult, internal, human, ChainError, profile};
/// Contains informations about how a package should be compiled.
fn scrape_target_config(config: &Config, triple: &str)
-> CargoResult<ops::TargetConfig> {
+
let key = format!("target.{}", triple);
let ar = try!(config.get_string(&format!("{}.ar", key)));
let linker = try!(config.get_string(&format!("{}.linker", key)));
let table = try!(config.get_table(&key)).unwrap().0;
for (k, _) in table.into_iter() {
let key = format!("{}.{}", key, k);
- let (v, path) = try!(config.get_string(&key)).unwrap();
- if k == "rustc-flags" {
- let whence = format!("in `{}` (in {:?})", key, path);
- let (paths, links) = try!(
- BuildOutput::parse_rustc_flags(&v, &whence)
- );
- output.library_paths.extend(paths.into_iter());
- output.library_links.extend(links.into_iter());
- } else {
- output.metadata.push((k, v));
+ match try!(config.get(&key)).unwrap() {
+ ConfigValue::String(v, path) => {
+ if k == "rustc-flags" {
+ let whence = format!("in `{}` (in {:?})", key, path);
+ let (paths, links) = try!(
+ BuildOutput::parse_rustc_flags(&v, &whence)
+ );
+ output.library_paths.extend(paths.into_iter());
+ output.library_links.extend(links.into_iter());
+ } else {
+ output.metadata.push((k, v));
+ }
+ },
+ ConfigValue::List(a, p) => {
+ if k == "rustc-link-lib" {
+ output.library_links.extend(a.into_iter().map(|(v, _)| v));
+ } else if k == "rustc-link-search" {
+ output.library_paths.extend(a.into_iter().map(|(v, _)| PathBuf::new(&v)));
+ } else {
+ try!(config.expected("string", &k, ConfigValue::List(a, p)));
+ }
+ },
+ // technically could be a list too, but that's the exception to the rule...
+ cv => { try!(config.expected("string", &k, cv)); }
}
}
ret.overrides.insert(lib_name, output);
);
library_links.extend(links.into_iter());
library_paths.extend(libs.into_iter());
+ } else if key == "rustc-link-lib" {
+ library_links.push(value.to_string());
+ } else if key == "rustc-link-search" {
+ library_paths.push(PathBuf::new(&value));
} else {
metadata.push((key.to_string(), value.to_string()))
}
}
}
+ pub fn get_list(&self, key: &str) -> CargoResult<Option<(Vec<(String, PathBuf)>, PathBuf)>> {
+ match try!(self.get(key)) {
+ Some(CV::List(i, path)) => Ok(Some((i, path))),
+ Some(val) => self.expected("list", key, val),
+ None => Ok(None),
+ }
+ }
+
pub fn get_table(&self, key: &str)
-> CargoResult<Option<(HashMap<String, CV>, PathBuf)>> {
match try!(self.get(key)) {
Example output:
```notrust
-cargo:rustc-flags=-l static=foo -L native=/path/to/foo
+cargo:rustc-link-lib=static=foo
+cargo:rustc-link-search=native=/path/to/foo
cargo:root=/path/to/foo
cargo:libdir=/path/to/foo/lib
cargo:include=/path/to/foo/include
```
+The `rustc-link-lib` key indicates that Cargo should pass a `-l` option to
+rustc. Similarly, `rustc-link-search` indicates that Cargo should pass a `-L`
+option.
+
The `rustc-flags` key is special and indicates the flags that Cargo will
-pass to Rustc. Currently only `-l` and `-L` are accepted.
+pass to Rustc. Currently only `-l` and `-L` are accepted. Using
+`rustc-link-lib` and `rustc-link-search` is more robust.
Any other element is a user-defined metadata that will be passed to
dependencies. More information about this can be found in the [`links`][links]
```toml
[target.x86_64-unknown-linux-gnu.foo]
-rustc-flags = "-L /path/to/foo -l foo"
+rustc-link-search = ["/path/to/foo"]
+rustc-link-lib = ["foo"]
root = "/path/to/foo"
key = "value"
```
This section states that for the target `x86_64-unknown-linux-gnu` the library
named `foo` has the metadata specified. This metadata is the same as the
metadata generated as if the build script had run, providing a number of
-key/value pairs where the `rustc-flags` key is slightly special.
+key/value pairs where the `rustc-flags`, `rustc-link-search`, and
+`rustc-link-lib` keys are slightly special.
With this configuration, if a package declares that it links to `foo` then the
build script will **not** be compiled or run, and the metadata specified will
.current_dir(&Path::new(&out_dir))
.status().unwrap();
- println!("cargo:rustc-flags=-L native={} -l static=hello", out_dir);
+ println!("cargo:rustc-link-search=native={}", out_dir);
+ println!("cargo:rustc-link-lib=static=hello");
}
```
", compiling = COMPILING, running = RUNNING).as_slice()));
});
+test!(propagation_of_l_flags_new {
+ let (_, target) = ::cargo::ops::rustc_version().unwrap();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ links = "bar"
+ build = "build.rs"
+
+ [dependencies.b]
+ path = "../b"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-link-search=bar");
+ }
+ "#)
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ links = "foo"
+ build = "build.rs"
+ "#)
+ .file("b/src/lib.rs", "")
+ .file("b/build.rs", "bad file")
+ .file(".cargo/config", format!(r#"
+ [target.{}.foo]
+ rustc-link-search = ["foo"]
+ "#, target).as_slice());
+
+ assert_that(p.cargo_process("build").arg("-v").arg("-j1"),
+ execs().with_status(0)
+ .with_stdout(format!("\
+[..]
+[..]
+[..]
+[..]
+{running} `[..]a-[..]build-script-build[..]`
+{running} `rustc [..] --crate-name a [..]-L bar[..]-L foo[..]`
+{compiling} foo v0.5.0 (file://[..])
+{running} `rustc [..] --crate-name foo [..] -L bar -L foo`
+", compiling = COMPILING, running = RUNNING).as_slice()));
+});
+
test!(build_deps_simple {
let p = project("foo")
.file("Cargo.toml", r#"
", compiling = COMPILING, running = RUNNING).as_slice()));
});
+test!(output_separate_lines_new {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-link-search=foo");
+ println!("cargo:rustc-link-lib=static=foo");
+ }
+ "#);
+ assert_that(p.cargo_process("build").arg("-v"),
+ execs().with_status(101)
+ .with_stdout(format!("\
+{compiling} foo v0.5.0 (file://[..])
+{running} `rustc build.rs [..]`
+{running} `[..]foo-[..]build-script-build[..]`
+{running} `rustc [..] --crate-name foo [..] -L foo -l static=foo`
+", compiling = COMPILING, running = RUNNING).as_slice()));
+});
+
#[cfg(not(windows))] // FIXME(#867)
test!(code_generation {
let p = project("foo")